// Локальные
#include "approximation/interpolation.h"

namespace approximation
{
	//============================================================================================================================
	//============================================================================================================================
	QList<double> Interpolation::interpolate(const QList<double> &arguments, const QList<double> &values, const QList<double> &points, Algorithm algorithm)
	{
		QList<double> interpolated_values;

		switch(algorithm)
		{
		case Linear:
			interpolated_values = linearInterpolation(arguments, values, points);
			break;
		default:
			qWarning("Unknown algorithm");
		}
		return interpolated_values;
	}

	//============================================================================================================================
	//============================================================================================================================
        QList< QVector<double> > Interpolation::interpolate(const QList<double> &arguments, const QList<double> &values, int num_of_points, Algorithm algorithm)
	{
		QList<double> points;
		for(int i = 0; i < num_of_points; i++)
			points.append(arguments.first() + (i + 1)*(arguments.last() - arguments.first())/(num_of_points + 1));

		QList<double> interpolated_values = interpolate(arguments, values, points, algorithm);

                QList< QVector<double> > result;
		for(int i = 0; i < points.size(); ++i)
		{
			result.append(QVector<double>(2));
			result.last()[0] = points[i];
			result.last()[1] = interpolated_values[i];
		}
		return result;
	}

	//============================================================================================================================
	//============================================================================================================================
	QList<double> Interpolation::linearInterpolation(const QList<double> &arguments, const QList<double> &values, const QList<double> &points)
	{
		Q_ASSERT_X(arguments.size() == values.size(), "Interpolation::linearInterpolation", "counts of arguments and values don't match");

		QList<double> interpolated_values;
		for(int i = 0; i < points.size(); ++i)
		{
			Q_ASSERT_X(arguments.first() <= points[i] && points[i] <= arguments.last(), "Interpolation::linearInterpolation", "Extrapolation is needed");

			int j = 0;
			if(arguments.first() < arguments.last())
				while(!(arguments[j] <= points[i] && points[i] <= arguments[j + 1]))
					j++;
			else
				while(!(arguments[j] >= points[i] && points[i] >= arguments[j + 1]))
					j++;

			interpolated_values.append(((arguments[j + 1] - points[i])*values[j] + (points[i] - arguments[j])*values[j + 1])/(arguments[j + 1] - arguments[j]));
		}
		return interpolated_values;
	}
}
